/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package vinahelper;

import datafactory.GridReader;
import datastructures.VinaParams;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.*;
import java.util.Locale;
import java.util.StringTokenizer;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.vecmath.Point3d;

/**
 *
 * @author Paolo
 */
public class VHFrame extends javax.swing.JFrame {
    public static final File configFile = new File(System.getenv("HOME") + "/.vinahelper");
    public static File workingDir, vinaFile;
    
    private File gridFile, ligandFile;
    private VinaParams vinaParams;
    
    /**
     * Creates new form VHFrame
     */
    public VHFrame() {
        gridFile = ligandFile;
        vinaParams = null;
        
        initComponents();
        
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        setLocation((dim.width - getSize().width) / 2, (dim.height - getSize().height) / 2); 
    }
    
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        optionsPanel = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        cpuSlider = new javax.swing.JSlider();
        jLabel3 = new javax.swing.JLabel();
        exhaustivenessTextField = new javax.swing.JTextField();
        jLabel4 = new javax.swing.JLabel();
        modesTextField = new javax.swing.JTextField();
        dockingButton = new javax.swing.JButton();
        progressBar = new javax.swing.JProgressBar();
        menuBar = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        ligandMenuItem = new javax.swing.JMenuItem();
        gridMenuItem = new javax.swing.JMenuItem();
        fileMenuSeparator = new javax.swing.JPopupMenu.Separator();
        exitMenuItem = new javax.swing.JMenuItem();
        editMenu = new javax.swing.JMenu();
        vinaMenuItem = new javax.swing.JMenuItem();
        helpMenu = new javax.swing.JMenu();
        aboutMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Vina Helper");
        setIconImage(new ImageIcon (getClass().getResource("/data/icon.png")).getImage());

        optionsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Options"));

        jLabel2.setText("Number of CPUs:");

        cpuSlider.setMajorTickSpacing(1);
        cpuSlider.setMaximum(Runtime.getRuntime().availableProcessors());
        cpuSlider.setMinimum(1);
        cpuSlider.setMinorTickSpacing(1);
        cpuSlider.setPaintLabels(true);
        cpuSlider.setSnapToTicks(true);

        jLabel3.setText("Exhaustiveness:");

        exhaustivenessTextField.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
        exhaustivenessTextField.setText("9");

        jLabel4.setText("Number of modes:");

        modesTextField.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
        modesTextField.setText("8");

        dockingButton.setText("Start Docking!");
        dockingButton.setEnabled(false);
        dockingButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                dockingButtonActionPerformed(evt);
            }
        });

        org.jdesktop.layout.GroupLayout optionsPanelLayout = new org.jdesktop.layout.GroupLayout(optionsPanel);
        optionsPanel.setLayout(optionsPanelLayout);
        optionsPanelLayout.setHorizontalGroup(
            optionsPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(optionsPanelLayout.createSequentialGroup()
                .addContainerGap()
                .add(optionsPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, optionsPanelLayout.createSequentialGroup()
                        .add(optionsPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(jLabel2)
                            .add(jLabel3)
                            .add(jLabel4))
                        .add(18, 18, 18)
                        .add(optionsPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(optionsPanelLayout.createSequentialGroup()
                                .add(6, 6, 6)
                                .add(optionsPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                    .add(modesTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 65, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                    .add(exhaustivenessTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 65, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                                .add(18, 18, 18)
                                .add(dockingButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
                            .add(optionsPanelLayout.createSequentialGroup()
                                .add(cpuSlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 209, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                .add(0, 0, Short.MAX_VALUE))))
                    .add(progressBar, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        optionsPanelLayout.setVerticalGroup(
            optionsPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(optionsPanelLayout.createSequentialGroup()
                .add(optionsPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(cpuSlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(optionsPanelLayout.createSequentialGroup()
                        .addContainerGap()
                        .add(jLabel2)))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                .add(optionsPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                    .add(optionsPanelLayout.createSequentialGroup()
                        .add(optionsPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(modesTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                            .add(jLabel3))
                        .add(12, 12, 12)
                        .add(optionsPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(jLabel4)
                            .add(exhaustivenessTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                    .add(dockingButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .add(24, 24, 24)
                .add(progressBar, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        fileMenu.setText("File");

        ligandMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/data/open.png"))); // NOI18N
        ligandMenuItem.setText("Open ligand file...");
        ligandMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ligandMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(ligandMenuItem);

        gridMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/data/open.png"))); // NOI18N
        gridMenuItem.setText("Open grid file...");
        gridMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                gridMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(gridMenuItem);
        fileMenu.add(fileMenuSeparator);

        exitMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/data/exit.png"))); // NOI18N
        exitMenuItem.setText("Exit");
        exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exitMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        editMenu.setText("Edit");

        vinaMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/data/exe.png"))); // NOI18N
        vinaMenuItem.setText("Vina executable file...");
        vinaMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                vinaMenuItemActionPerformed(evt);
            }
        });
        editMenu.add(vinaMenuItem);

        menuBar.add(editMenu);

        helpMenu.setText("Help");

        aboutMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/data/about.png"))); // NOI18N
        aboutMenuItem.setText("About...");
        aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                aboutMenuItemActionPerformed(evt);
            }
        });
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        setJMenuBar(menuBar);

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(optionsPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(optionsPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void dockingButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dockingButtonActionPerformed
        int exhaustiveness, modes, cpu;
        Point3d center;
        double width, height, depth;
        
        if (vinaFile != null && vinaFile.isFile()) {
        
            cpu = cpuSlider.getValue();

            try{
                exhaustiveness = Integer.parseInt(exhaustivenessTextField.getText());
                if (exhaustiveness < 1)
                    throw new NumberFormatException();
            }
            catch (NumberFormatException nfe) {
                JOptionPane.showMessageDialog(this, "The exhaustiveness should be greater than 0!", "ERROR!", JOptionPane.ERROR_MESSAGE);
                return;
            }

            try{
                modes = Integer.parseInt(modesTextField.getText());
                if (modes < 1)
                    throw new NumberFormatException();
            }
            catch (NumberFormatException nfe) {
                JOptionPane.showMessageDialog(this, "The number of modes should be a greater than 0!", "ERROR!", JOptionPane.ERROR_MESSAGE);
                return;
            }
            
            vinaParams.setCpu(cpu);
            vinaParams.setExhaustiveness(exhaustiveness);
            vinaParams.setModes(modes);
            
            
            dockingButton.setEnabled(false);
            gridMenuItem.setEnabled(false);
            ligandMenuItem.setEnabled(false);
            vinaMenuItem.setEnabled(false);
            cpuSlider.setEnabled(false);
            exhaustivenessTextField.setEnabled(false);
            modesTextField.setEnabled(false);
            
            new DockingThread(this, ligandFile, vinaParams).start();
        }
        else {
            JOptionPane.showMessageDialog(this, "Choose Vina executable first!", "WARNING!", JOptionPane.WARNING_MESSAGE);
        }
    }//GEN-LAST:event_dockingButtonActionPerformed

    private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
        setVisible(false);
        dispose();
        System.exit(0);
    }//GEN-LAST:event_exitMenuItemActionPerformed

    private void gridMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gridMenuItemActionPerformed
        File file;
        JFileChooser open = new JFileChooser();
        
        dockingButton.setEnabled(false);
        
        open.setDialogTitle("Open");
        open.setDialogType(JFileChooser.OPEN_DIALOG);
        open.setAcceptAllFileFilterUsed(false);
        open.setFileFilter(new FileNameExtensionFilter("AutoGrid file", "gpf", "GPF"));
        
        if (gridFile != null && gridFile.isFile()) {
            open.setCurrentDirectory(gridFile);
            open.setSelectedFile(gridFile);
        }
        else if (workingDir != null && workingDir.isDirectory()) {
            open.setCurrentDirectory(workingDir);
        }
        
        if (open.showOpenDialog(this) == JFileChooser.APPROVE_OPTION &&
                (file = open.getSelectedFile()) != null) {
            
            gridFile = file;
            updateWorkingDir (file);
            
            vinaParams = GridReader.readGrid(gridFile);
            
            if (vinaParams != null && ligandFile != null && ligandFile.isFile()){
                dockingButton.setEnabled(true);
            }
        }
    }//GEN-LAST:event_gridMenuItemActionPerformed

    private void ligandMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ligandMenuItemActionPerformed
        File file;
        JFileChooser open = new JFileChooser();
        
        dockingButton.setEnabled(false);
        
        open.setDialogTitle("Open");
        open.setDialogType(JFileChooser.OPEN_DIALOG);
        open.setAcceptAllFileFilterUsed(false);
        open.setFileFilter(new FileNameExtensionFilter("PDBQT file", "pdbqt", "PDBQT"));
        
        if (ligandFile != null && ligandFile.isFile()) {
            open.setCurrentDirectory(ligandFile);
            open.setSelectedFile(ligandFile);
        }
        else if (workingDir != null && workingDir.isDirectory()) {
            open.setCurrentDirectory(workingDir);
        }
        
        if (open.showOpenDialog(this) == JFileChooser.APPROVE_OPTION &&
                (file = open.getSelectedFile()) != null) {
            
            ligandFile = file;
            updateWorkingDir (file);
            
            if (vinaParams != null && gridFile != null && gridFile.isFile()){
                dockingButton.setEnabled(true);
            }
        }
    }//GEN-LAST:event_ligandMenuItemActionPerformed

    private void vinaMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_vinaMenuItemActionPerformed
        File file;
        JFileChooser open = new JFileChooser();
        
        open.setDialogTitle("Open");
        open.setDialogType(JFileChooser.OPEN_DIALOG);
        
        if (vinaFile != null && vinaFile.isFile()) {
            open.setCurrentDirectory(vinaFile);
            open.setSelectedFile(vinaFile);
        }
        
        if (open.showOpenDialog(this) == JFileChooser.APPROVE_OPTION &&
                (file = open.getSelectedFile()) != null) {
            updateVinaFile(file);
        }
    }//GEN-LAST:event_vinaMenuItemActionPerformed

    private void aboutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_aboutMenuItemActionPerformed
        String message = "\n    Vina Helper\n" +
                         "    Version 1.0\n\n" + 
                         "© 2012 - Paolo Gatti\n" +
                         "n3o.eden@gmail.com";
        JOptionPane.showMessageDialog(this, message, "About...", JOptionPane.PLAIN_MESSAGE,
                new ImageIcon(getClass().getResource("/data/aboutImg.png")));
    }//GEN-LAST:event_aboutMenuItemActionPerformed
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        
        if (configFile.isFile()) {
            
            try {
                String line, key, value;
                String content = "";
                BufferedReader in = new BufferedReader (new FileReader (configFile));
                
                while ((line = in.readLine()) != null) {
                    content += line + "\n";
                }
                in.close();
                
                StringTokenizer t = new StringTokenizer(content, "\n"), t2;
                
                while (t.hasMoreTokens()) {
                    line = t.nextToken();
                    t2 = new StringTokenizer (line, "=");
                    key = t2.nextToken().trim();
                    value = t2.nextToken().trim();
                    if (key.equals("VinaFile")) {
                        vinaFile = new File (value);
                    }
                    else if (key.equals("WorkingDir")) {
                        workingDir = new File (value);
                    }
                    else {
                        throw new IOException();
                    }
                }
                in.close();
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
            }
        }
        
        
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(VHFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(VHFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(VHFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(VHFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>
        
        /*
         * Create and display the form
         */
        Locale.setDefault(Locale.US);
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new VHFrame().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem aboutMenuItem;
    javax.swing.JSlider cpuSlider;
    javax.swing.JButton dockingButton;
    private javax.swing.JMenu editMenu;
    javax.swing.JTextField exhaustivenessTextField;
    private javax.swing.JMenuItem exitMenuItem;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JPopupMenu.Separator fileMenuSeparator;
    javax.swing.JMenuItem gridMenuItem;
    private javax.swing.JMenu helpMenu;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    javax.swing.JMenuItem ligandMenuItem;
    private javax.swing.JMenuBar menuBar;
    javax.swing.JTextField modesTextField;
    private javax.swing.JPanel optionsPanel;
    javax.swing.JProgressBar progressBar;
    javax.swing.JMenuItem vinaMenuItem;
    // End of variables declaration//GEN-END:variables

    private static void updateVinaFile(File file) {
        vinaFile = file;
        
        boolean keyFound = false;
        try {
            if (configFile.isFile()) {
                String line, line2, key, value;
                String content = "";
                BufferedReader in = new BufferedReader (new FileReader (configFile));

                while ((line = in.readLine()) != null) {
                    content += line + "\n";
                }
                in.close();

                PrintWriter out = new PrintWriter (new FileWriter (configFile));
                StringTokenizer t = new StringTokenizer(content, "\n"), t2;

                while (t.hasMoreTokens()) {
                    line2 = t.nextToken();
                    t2 = new StringTokenizer (line2, "=");
                    key = t2.nextToken().trim();
                    value = t2.nextToken().trim();
                    if (! key.equals("VinaFile")) {
                        out.println(line2);
                    }
                    else {
                        keyFound = true;
                        out.println("VinaFile = " + vinaFile.getPath());
                    }
                }
                if (! keyFound) {
                    out.println("VinaFile = " + vinaFile.getPath());
                }
                out.close();
            }
            else {
                PrintWriter out = new PrintWriter (new FileWriter (System.getenv("HOME") + "/.vinahelper"));
                out.println("VinaFile = " + vinaFile.getPath());
                out.close();
            }

        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
    }
    
    private static void updateWorkingDir(File file) {
        workingDir = file.getParentFile();
        
        boolean keyFound = false;
        try {
            if (configFile.isFile()) {
                String line, line2, key, value;
                String content = "";
                BufferedReader in = new BufferedReader (new FileReader (configFile));

                while ((line = in.readLine()) != null) {
                    content += line + "\n";
                }
                in.close();

                PrintWriter out = new PrintWriter (new FileWriter (configFile));
                StringTokenizer t = new StringTokenizer(content, "\n"), t2;
                
                while (t.hasMoreTokens()) {
                    line2 = t.nextToken();
                    t2 = new StringTokenizer (line2, "=");
                    key = t2.nextToken().trim();
                    value = t2.nextToken().trim();
                    if (! key.equals("WorkingDir")) {
                        out.println(line2);
                    }
                    else {
                        keyFound = true;
                        out.println ("WorkingDir = " + workingDir.getPath());
                    }
                }
                if (! keyFound) {
                    out.println ("WorkingDir = " + workingDir.getPath());
                }
                out.close();
            }
            else {
                PrintWriter out = new PrintWriter (new FileWriter (System.getenv("HOME") + "/.vinahelper"));
                out.println("WorkingDir = " + workingDir.getPath());
                out.close();
            }

        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
    }
}
